package com.mjk.common.ai.service;


import com.mjk.common.ai.base.ThreadContext;
import com.mjk.common.ai.entity.AdiFile;
import com.mjk.common.ai.entity.User;
import com.mjk.common.ai.enums.ErrorEnum;
import com.mjk.common.ai.exception.BaseException;
import com.mjk.common.ai.helper.AdiFileHelper;
import com.mjk.common.ai.util.HashUtil;
import com.mjk.common.ai.util.LocalFileUtil;
import com.mjk.common.ai.vo.SaveRemoteImageResult;
import com.mjk.common.core.jdbc.service.plus.idbservice.BeeDBService;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.util.RandomUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static com.mjk.common.ai.enums.ErrorEnum.A_AI_IMAGE_NO_AUTH;
import static com.mjk.common.ai.enums.ErrorEnum.A_FILE_NOT_EXIST;

@Slf4j
@Service
public class FileService {

    @Value("${local.images}")
    private String imagePath;

    @Value("${local.watermark-images}")
    private String watermarkImagesPath;

    @Value("${local.thumbnails}")
    private String thumbnailsPath;

    @Value("${local.watermark-thumbnails}")
    private String watermarkThumbnailsPath;

    @Value("${local.files}")
    private String filePath;

    @Value("${local.tmp-images}")
    private String tmpImagesPath;

    @Resource
    private AdiFileHelper adiFileHelper;

    @Autowired
    private BeeDBService beeDBService;

    public AdiFile saveFile(MultipartFile file, boolean image) {
        String sha256 = HashUtil.sha256(file);
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);

        AdiFile existFile = wrapper
                .eq(AdiFile::getSha256, sha256)
                .eq(AdiFile::getIsDeleted, false).one();

        if (existFile != null) {
            boolean exist = adiFileHelper.checkIfExist(existFile);
            if (exist) {
                return existFile;
            } else {
                log.warn("文件不存在,删除记录以便后续重新生成,fileId:{},uuid:{},sha256:{}", existFile.getId(), existFile.getUuid(), existFile.getSha256());
                wrapper = new BeeQueryWrapper(AdiFile.class);
                wrapper.eq(AdiFile::getId, existFile.getId());
                existFile.setIsDeleted(true);
                beeDBService.update(wrapper);
            }
        }
        String uuid = RandomUtil.getShortUuid();
        Pair<String, String> originalFile = adiFileHelper.save(file, image, uuid);
        AdiFile adiFile = new AdiFile();
        adiFile.setName(file.getOriginalFilename());
        adiFile.setUuid(uuid);
        adiFile.setSha256(sha256);
        adiFile.setPath(originalFile.getLeft());
        adiFile.setExt(originalFile.getRight());
        adiFile.setUserId(ThreadContext.getCurrentUserId());
        adiFile.setStorageLocation(AdiFileHelper.getStorageLocation());
        beeDBService.insert(adiFile);
        return adiFile;
    }

    public String saveImageFromUrl(User user, String sourceImageUrl) {
        log.info("saveImageFromUrl,sourceImageUrl:{}", sourceImageUrl);
        String uuid = RandomUtil.getShortUuid();
        SaveRemoteImageResult saveResult = adiFileHelper.saveImageFromUrl(sourceImageUrl, uuid);
        AdiFile adiFile = new AdiFile();
        adiFile.setName(saveResult.getOriginalName());
        adiFile.setUuid(uuid);
        adiFile.setSha256(HashUtil.sha256(saveResult.getPathOrUrl()));
        adiFile.setPath(saveResult.getPathOrUrl());
        adiFile.setUserId(user.getId());
        adiFile.setExt(saveResult.getExt());
        adiFile.setStorageLocation(AdiFileHelper.getStorageLocation());
        beeDBService.insert(adiFile);
        return uuid;
    }

    public boolean softDel(String uuid) {
        AdiFile file = new AdiFile();
        file.setIsDeleted(true);
        BeeQueryWrapper wrapper = new BeeQueryWrapper(file);
        wrapper.eq(AdiFile::getUserId, ThreadContext.getCurrentUserId())
                .eq(AdiFile::getUuid, uuid);
        return beeDBService.update(wrapper) > 0;
    }

    public boolean removeFileAndSoftDel(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUserId, ThreadContext.getCurrentUserId())
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            return false;
        }
        adiFileHelper.delete(adiFile);
        return this.softDel(uuid);
    }

    public AdiFile getByUuid(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        return wrapper
                .eq(AdiFile::getUuid, uuid)
                .eq(AdiFile::getUserId, ThreadContext.getCurrentUserId())
                .one();
    }

    /**
     * 读取图片到BufferedImage，管理员或图片拥有者才有权限查看
     *
     * @param uuid      图片uuid
     * @param thumbnail 读取的是缩略图
     * @return 图片内容
     */
    public BufferedImage readMyImage(String uuid, boolean thumbnail) {
        if (StringUtils.isBlank(ThreadContext.getToken())) {
            throw new BaseException(A_AI_IMAGE_NO_AUTH);
        }
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        if (!ThreadContext.getCurrentUser().getIsAdmin()) {
            wrapper.eq(AdiFile::getUserId, ThreadContext.getCurrentUserId());
        }
        wrapper.eq(AdiFile::getUuid, uuid);
        AdiFile adiFile = (AdiFile) beeDBService.findOneByWrapper(wrapper);
        if (null == adiFile) {
            throw new BaseException(A_FILE_NOT_EXIST);
        }
        return LocalFileUtil.readLocalImage(adiFile, thumbnail, thumbnailsPath);
    }

    public BufferedImage readImage(String uuid, boolean thumbnail) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            throw new BaseException(A_FILE_NOT_EXIST);
        }
        return LocalFileUtil.readLocalImage(adiFile, thumbnail, thumbnailsPath);
    }

    public String getImagePath(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            throw new BaseException(ErrorEnum.A_AI_IMAGE_NOT_FOUND);
        }
        return adiFile.getPath();
    }


    public AdiFile getFile(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            throw new BaseException(ErrorEnum.A_AI_IMAGE_NOT_FOUND);
        }
        return adiFile;
    }

    public String getTmpImagesPath(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            throw new BaseException(ErrorEnum.A_AI_IMAGE_NOT_FOUND);
        }
        return tmpImagesPath + uuid + "." + adiFile.getExt();
    }

    public String getWatermarkImagesPath(String uuid) {
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        AdiFile adiFile = wrapper
                .eq(AdiFile::getUuid, uuid)
                .one();
        if (null == adiFile) {
            throw new BaseException(ErrorEnum.A_AI_IMAGE_NOT_FOUND);
        }
        return watermarkImagesPath + uuid + "." + adiFile.getExt();
    }

    public String getWatermarkImagesPath(AdiFile adiFile) {
        return watermarkImagesPath + adiFile.getUuid() + "." + adiFile.getExt();
    }

    public String getUrl(String fileUuid) {
        if (StringUtils.isBlank(fileUuid)) {
            return null;
        }
        List<String> list = getUrls(List.of(fileUuid));
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 获取文件url
     *
     * @param fileUuids 文件uuid
     * @return 文件url
     */
    public List<String> getUrls(List<String> fileUuids) {
        if (CollectionUtils.isEmpty(fileUuids)) {
            return Collections.emptyList();
        }
        List<String> result = new ArrayList<>();
        BeeQueryWrapper wrapper = new BeeQueryWrapper(AdiFile.class);
        List<AdiFile> files = wrapper
                .in(AdiFile::getUuid, fileUuids)
                .eq(AdiFile::getIsDeleted, false)
                .list();

        files.forEach(adiFile -> {
            result.add(adiFileHelper.getFileUrl(adiFile));
        });
        return result;
    }
}
